package com.simple.framework.security.custom;

import com.github.zuihou.base.R;
import com.simple.business.domain.vo.login.UserLoginSuccessVO;
import com.simple.business.service.user.UserService;
import com.simple.framework.web.service.ProviderAuthenticationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Optional;

@Slf4j
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    List<ProviderAuthenticationService> providerAuthenticationServiceList;

    @Resource
    UserService userService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Authentication result = new LoginFailToken();
        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            // 普通账号密码登录
            UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
            UserLoginSuccessVO login = userService.login(token.getPrincipal().toString(), token.getCredentials().toString());
            if (login != null) {
                result = new LoginSuccessToken(login);
                result.setAuthenticated(true);
            }else{
                ((LoginFailToken) result).setFailResult("账号或者密码错误");
            }
        } else if (authentication instanceof ThirdAuthenticationToken) {
            // 第三方登录
            if (!(RequestContextHolder.currentRequestAttributes() instanceof ServletRequestAttributes)) {
                ((LoginFailToken) result).setFailResult("请求异常");
                return result;
            }
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
            ThirdAuthenticationToken thirdAuthenticationToken = (ThirdAuthenticationToken) authentication;
            Optional<ProviderAuthenticationService> providerAuthenticationService = providerAuthenticationServiceList.stream()
                    .filter(p -> p.supportsProvider().contains(thirdAuthenticationToken.getThirdAuthenticationEnum())).findFirst();
            if (providerAuthenticationService.isPresent()) {
                R<UserLoginSuccessVO> authenticate = providerAuthenticationService.get().authenticate(thirdAuthenticationToken, request);
                if (authenticate.getIsSuccess()) {
                    result = new LoginSuccessToken(authenticate.getData());
                    result.setAuthenticated(true);
                } else {
                    log.warn("第三方验证失败:{}", authenticate);
                    LoginFailToken failToken = ((LoginFailToken) result);
                    failToken.setFailResult(authenticate.getCode(),authenticate.getMsg());
                    return result;
                }
            }
        }
        if (result.isAuthenticated()) {
            //返回LoginSuccessToken
            SecurityContextHolder.getContext().setAuthentication(result);
        }
        return result;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class) || authentication.equals(ThirdAuthenticationToken.class);
    }
}
